﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="With_Guard.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the GuardTests type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Testing;

    [TestClass]
    public class With_Guard
    {
        [TestMethod]
        public void When_argument_null_with_null_reference_type_should_throw()
        {
            object test = null;
            Assert.AreEqual("test", AssertException.Throws<ArgumentNullException>(
                () => Guard.ArgumentNull("test", test)).ParamName);
        }

        [TestMethod]
        public void When_argument_null_with_not_null_reference_type_should_not_throw()
        {
            Guard.ArgumentNull("test", new object());
        }

        [TestMethod]
        public void When_argument_null_with_null_nullable_type_should_throw()
        {
            int? test = null;
            Assert.AreEqual("test", AssertException.Throws<ArgumentNullException>(
                () => Guard.ArgumentNull("test", test)).ParamName);
        }

        [TestMethod]
        public void When_argument_null_with_not_null_nullable_type_should_not_throw()
        {
            int? test = 1;
            Guard.ArgumentNull("test", test);
        }

        [TestMethod]
        public void When_argument_less_than_with_int_less_than_should_throw()
        {
            var exception = AssertException.Throws<ArgumentOutOfRangeException>(
                () => Guard.ArgumentLessThan("test", 0, 1));
            AssertExceptionEquals(exception, "test", 0);
        }

        [TestMethod]
        public void When_argument_less_than_with_int_greater_than_should_throw()
        {
            var exception = AssertException.Throws<ArgumentOutOfRangeException>(
                () => Guard.ArgumentGreaterThan("test", 1, 0));
            AssertExceptionEquals(exception, "test", 1);
        }

        [TestMethod]
        public void When_argument_out_of_range_with_int_out_of_range_should_throw()
        {
            var exception = AssertException.Throws<ArgumentOutOfRangeException>(
                () => Guard.ArgumentOutOfRange("test", -1, 0, 1));
            AssertExceptionEquals(exception, "test", -1);

            exception = AssertException.Throws<ArgumentOutOfRangeException>(
                () => Guard.ArgumentOutOfRange("test", 2, 0, 1));
            AssertExceptionEquals(exception, "test", 2);
        }

        [TestMethod]
        public void When_argument_null_or_wrong_type_with_wrong_type_should_throw()
        {
            Assert.AreEqual("test", AssertException.Throws<ArgumentException>(
                () => Guard.ArgumentNullOrWrongType<int>("test", 1.0)).ParamName);
        }

        [TestMethod]
        public void When_argument_null_or_wrong_type_with_null_should_throw()
        {
            Assert.AreEqual("test", AssertException.Throws<ArgumentNullException>(
                () => Guard.ArgumentNullOrWrongType<int>("test", null)).ParamName);
        }
        
        private static void AssertExceptionEquals(ArgumentOutOfRangeException exception, string argumentName, object actualValue)
        {
            Assert.AreEqual(argumentName, exception.ParamName);
            Assert.AreEqual(actualValue, exception.ActualValue);
        }
    }
}
